package servidor.controladorsistema.rn;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import servidor.controladorsistema.ip.IPControladorSistema;
import servidor.controladorsistema.ip.IPDAOPerfilFactory;
import servidor.controladorsistema.ip.IPDAOResultadoPartidaFactory;
import servidor.controladorsistema.ip.IPPerfil;
import servidor.controladorsistema.ip.IPResultadoPartida;
import servidor.controladorsistema.ip.IPSituacaoResultadoPartida;

import comum.rn.RNEntradaRanking;
import comum.rn.RNEstatisticas;
import comum.rn.RNEstatisticasPessoais;
import comum.so.exception.FalhaComunicacaoBancoDadosException;
import comum.so.exception.FalhaValidacaoException;
import comum.so.exception.JaExistePerfilCadastradoComEsseLoginException;
import comum.so.exception.LoginEmUsoException;

public class RNControladorSistema {

	private List<String> usuariosLogados;
	private IPControladorSistema IPControlador;

	public RNControladorSistema() {
		setUsuariosLogados(new ArrayList<String>());
		setIPControlador(new IPControladorSistema());
	}

	public void validarLogin(String identificador, String senha)
			throws FalhaValidacaoException, LoginEmUsoException,
			FalhaComunicacaoBancoDadosException {
		boolean sucesso = getIPControlador().validarLogin(identificador, senha);
		if (!sucesso)
			throw new FalhaValidacaoException();
		if (getUsuariosLogados().contains(identificador))
			throw new LoginEmUsoException();
		getUsuariosLogados().add(identificador);
	}

	public void deslogar(String identificador) {
		getUsuariosLogados().remove(identificador);
	}

	public void cadastrarNovoPerfil(String identificador, String senha)
			throws JaExistePerfilCadastradoComEsseLoginException {
		if (IPDAOPerfilFactory.getDAO().recuperar(identificador) != null)
			throw new JaExistePerfilCadastradoComEsseLoginException();

		getIPControlador().cadastrarNovoPerfil(identificador, senha);
	}

	public RNEstatisticas obterEstatisticas(String identificador) {
		RNEstatisticasPessoais estatisticasPessoais = computarEstatisticasPessoais(identificador);
		List<RNEntradaRanking> ranking = computarRanking();
		return new RNEstatisticas(estatisticasPessoais, ranking);
	}

	private RNEstatisticasPessoais computarEstatisticasPessoais(
			String identificador) {
		Integer pontuacao = 0;
		Integer numeroPartidas = 0;
		Integer numeroVitorias = 0;
		Integer numeroDerrotas = 0;

		List<IPResultadoPartida> ipResultadosPartida = IPDAOResultadoPartidaFactory
				.getDAO().listarPorIdentificadorPerfil(identificador);
		for (IPResultadoPartida ipPontuacao : ipResultadosPartida) {
			pontuacao += ipPontuacao.getValor();
			if (ipPontuacao.getSituacao() == IPSituacaoResultadoPartida.VITORIA)
				++numeroVitorias;
			else if (ipPontuacao.getSituacao() == IPSituacaoResultadoPartida.DERROTA
					|| ipPontuacao.getSituacao() == IPSituacaoResultadoPartida.DESISTENCIA)
				++numeroDerrotas;
		}

		numeroPartidas = ipResultadosPartida.size();

		return new RNEstatisticasPessoais(pontuacao, numeroPartidas,
				numeroVitorias, numeroDerrotas);
	}

	private List<RNEntradaRanking> computarRanking() {
		List<IPPerfil> perfis = IPDAOPerfilFactory.getDAO().listar();
		List<RNEntradaRanking> ranking = new ArrayList<RNEntradaRanking>();
		for (int i = 0; i < perfis.size(); ++i) {
			String identificador = perfis.get(i).getIdentificador();
			int soma = 0;
			List<IPResultadoPartida> resultados = IPDAOResultadoPartidaFactory.getDAO().listarPorIdentificadorPerfil(identificador);
			for (int j = 0; j < resultados.size(); ++j)
				soma += resultados.get(j).getValor();
			ranking.add(new RNEntradaRanking(identificador, soma));
		}
		
		Collections.sort(ranking, new Comparator<RNEntradaRanking>() {
			@Override
			public int compare(RNEntradaRanking er1, RNEntradaRanking er2) {
				return er2.getPontuacao().compareTo(er1.getPontuacao());
			}
		});
		
		return ranking;
	}

	protected List<String> getUsuariosLogados() {
		return usuariosLogados;
	}

	protected void setUsuariosLogados(List<String> usuariosLogados) {
		this.usuariosLogados = usuariosLogados;
	}

	protected IPControladorSistema getIPControlador() {
		return IPControlador;
	}

	protected void setIPControlador(IPControladorSistema iPControlador) {
		IPControlador = iPControlador;
	}
}
